import http from '@/helpers/http'
import { useConstStore } from '@/stores/const'

const GOUV_ADRESSE_API_ENDPOINT = 'https://api-adresse.data.gouv.fr/search/'
const GOUV_GEO_API_ENDPOINT = 'https://geo.api.gouv.fr/communes'
const GOUV_COMPANY_API_ENDPOINT = 'https://recherche-entreprises.api.gouv.fr/search'


/**
 * 
 * @param {String} addressChunk : Adresse saisie par l'utilisateur
 * @param {Number} limit : Number of results to be returned
 * 
 * Renvoie le contenu de l'attribut "features" d'un objet de la forme suivante
 * {
  "type": "FeatureCollection",
  "version": "draft",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          3.446268,
          43.285072
        ]
      },
      "properties": {
        "label": "22ter Avenue Francois Mas 34300 Agde",
        "score": 0.8798472727272727,
        "housenumber": "22ter",
        "id": "34003_0794_00022_ter",
        "name": "22ter Avenue Francois Mas",
        "postcode": "34300",
        "citycode": "34003",
        "x": 736242.32,
        "y": 6242980.07,
        "city": "Agde",
        "context": "34, Hérault, Occitanie",
        "type": "housenumber",
        "importance": 0.67832,
        "street": "Avenue Francois Mas"
      }
    },
    ...
  ],
  "attribution": "BAN",
  "licence": "ETALAB-2.0",
  "query": "22ter avenue Françoi",
  "limit": 5
}
 */
export const findAddress = async (addressChunk, zipcode = '', limit = 25) => {
  let params = { q: addressChunk, limit: limit }
  if (zipcode) {
    params['postcode'] = zipcode
  }
  const query_params = new URLSearchParams(params)
  const url = `${GOUV_ADRESSE_API_ENDPOINT}?${query_params}`
  const result = await http.get(url)
  if (result['type'] === 'FeatureCollection') {
    return result.features
  } else {
    return []
  }
}
/**
 *
 * @param {String} zipCode
 *
 * Trouver une commune depuis un code postal
 */
export const findCity = async (searchObject) => {
  console.log('findCity')
  searchObject['limit'] = 5
  const query_params = new URLSearchParams(searchObject)
  const url = `${GOUV_GEO_API_ENDPOINT}?${query_params}`
  const result = await http.get(url)
  return result
}

export const addressFeatureToCustomerData = async (feature) => {
  const guess_street = await guessStreet(feature.name)
  const street_number = findStreetNumber(feature.name)
  return {
    address: feature.name,
    city: feature.city,
    city_code: feature.citycode,
    zip_code: feature.postcode,
    urssaf_data: {
      street_type: guess_street.street_type || '',
      street_name: guess_street.street_name || '',
      street_number: street_number.number || '',
      street_number_complement: street_number.complement || '',
      lieu_dit: '', // FIXME : peut-être une chose à trouver ici ?
    },
  }
}
/**
 * Retrouve un numéro de rue et éventuellement une lettre dans une adresse
 *
 * 2022-11-07 ! Pas utilisé à ce jour mais conservé au cas où
 *
 * @param {String} value : adresse de type 15 bis rue de genevilliers
 *
 * @returns: {'number': 15, 'complement': 'bis'}
 */
const REGEX = /^(?<number>[0-9]+)(\s)*(?<complement>(ter|bis|quarter)*)(\s)+/
const findStreetNumber = (value) => {
  let matched = value.match(REGEX)
  if (matched !== null) {
    return {
      number: matched.groups.number,
      complement: matched.groups.complement,
    }
  } else {
    return {}
  }
}

/**
 *
 * @param {String} address : l'adresse saisie par l'utilisateur ou renvoyée par l'api adresse
 * @returns : Le code du type de voie comme définie dans la nomenclature des types de voies (de l'urssaf et de la dgfip) et le nom de la voie
 *
 * Ex : rue -> R
 */
export const guessStreet = async (address) => {
  // On charge tous les types de voie
  let constStore = useConstStore()
  const streetTypes = await constStore.loadConst('street_types')
  // On construit une regexp permettant de matcher les types dans l'adresse
  let regexp = '(?<street_type>('
  streetTypes.forEach((item, index) => {
    regexp += item.name
    if (index < streetTypes.length - 1) {
      regexp += '|'
    }
  })
  regexp += '))(?<street_name>.+?)$'

  regexp = new RegExp(regexp, 'i')

  // On lance la regexp sur l'adresse et on voit ce qu'on récupère
  const match = address.match(regexp)
  let street_type = ''
  let street_name = ''
  if (match !== null) {
    street_type = match.groups['street_type']
    street_name = match.groups['street_name']
  }
  if (street_type) {
    // On retrouve le code qui va avec
    let res = streetTypes.find(
      (element) => element.name.toUpperCase() == street_type.toUpperCase()
    )
    if (res) {
      street_type = res.code
    } else {
      console.error('Type de voie introuvable')
      console.error(street_type)
      street_type = ''
    }
  }
  return { street_type: street_type, street_name: street_name }
}

/**
 * Tente de retrouver les informations administratives d'une adresse saisie manuellement
 * ou pas entièrement complétées (ex : adresse saisie manuellement, on active l'avance
 * immédiate en mode SAP, on a besoin du code ville et d'autres infos)
 *
 * si pas city_code, on tente l'api (parce qu'on ne l'aurait visiblement pas encore appelée)
 */
export const guessAddressData = async (address, zip_code, city, city_code) => {
  let result = {}
  console.log(address)
  console.log(zip_code)
  console.log(city)
  console.log(city_code)
  if (city_code) {
    console.log('On a déjà un city code, les données ont déjà été complétées')
    const guess_street = await guessStreet(address)
    const street_number = findStreetNumber(address)
    console.log(street_number)
    result = {
      address: address,
      zip_code: zip_code,
      city: city,
      city_code: city_code,
      urssaf_data: {
        street_type: guess_street.street_type || '',
        street_name: guess_street.street_name || '',
        street_number: street_number.number || '',
        street_number_complement: street_number.complement || '',
        lieu_dit: '', // FIXME : peut-être une chose à trouver ici ?
      },
    }
  } else if (address) {
    const queryResult = await findAddress(address, zip_code)
    if (queryResult.length == 1) {
      console.log(queryResult)
      result = addressFeatureToCustomerData(queryResult[0].properties)
    }
  }
  return result
}

/**
 * Tente de retrouver les informations administratives d'une entreprise à partir d'une recherche textuelle
 * 
 * @param {String} searchString : recherche textuelle, qui peut être aussi bien un numéro SIRET/SIREN qu'un nom
 * @param {Boolean} withEtablissements : est-ce qu'on ne veut le détails des établissements dans les résultats
 * @param {Integer} pageNumber : le numéro de la page de résultats que l'on veut récupérer
 *
 * @returns: Une liste d'objets JSON contenant les infos sur les entreprises correspondants à la recherche
 * 
 * Cf : https://recherche-entreprises.api.gouv.fr/docs
 */
export const findCompanyInfos = async (searchString, withEtablissements = false, pageNumber = 1) => {
  let results = []
  let optionalInfos = "siege"
  if (withEtablissements) {
    optionalInfos += ",matching_etablissements"
  }
  let params = {
    q: searchString,
    page: pageNumber,
    per_page: 25,
    minimal: true,
    include: optionalInfos
  }
  const query_params = new URLSearchParams(params)
  const url = `${GOUV_COMPANY_API_ENDPOINT}?${query_params}`
  const request = await http.get(url, null, null, false)
  if (request.total_results > 0) {
    let company_data = {}
    request.results.forEach(result => {
      company_data = {
          "siren": result["siren"],
          "name": result["nom_raison_sociale"],
          "address": [
            result["siege"]["numero_voie"],
            result["siege"]["type_voie"],
            result["siege"]["libelle_voie"]
          ].join(' '),
          "additional_address": result["siege"]["complement_adresse"],
          "zip_code": result["siege"]["code_postal"],
          "city": result["siege"]["libelle_commune"],
          "city_code": result["siege"]["commune"],
          "country": result["siege"]["libelle_pays_etranger"],
          "country_code": result["siege"]["code_pays_etranger"],
      }
      if(company_data["country"] == null) {
          company_data["country"] = "FRANCE"
          company_data["country_code"] = "99100"
      }
      results.push(company_data)
    });
  }
  return results
}
